package com.tanhua.server.service;

import com.alibaba.dubbo.config.annotation.Reference;
import com.tanhua.dubbo.server.api.SoundApi;
import com.tanhua.dubbo.server.pojo.Sound;
import com.tanhua.server.pojo.UserInfo;
import com.tanhua.server.utils.UserThreadLocal;
import com.tanhua.server.vo.PicUploadResult;
import com.tanhua.server.vo.SoundVo;
import org.apache.commons.lang3.RandomUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.client.utils.DateUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.util.ArrayList;
import java.util.Date;
import java.util.concurrent.TimeUnit;

@Service
public class SoundService {

    @Autowired
    private PicUploadService picUploadService;

    @Reference(version = "1.0.0")
    private SoundApi soundApi;

    @Autowired
    private RedisTemplate<String, String> redisTemplate;

    @Autowired
    private UserInfoService userInfoService;

    public String saveSound(MultipartFile file) {

        try {
            //音频文件上传至阿里云
            PicUploadResult upload = this.picUploadService.upload(file);
            String soundUrl = upload.getName();
            if (StringUtils.isEmpty(soundUrl)) {
                return null;
            }

            //保存数据至mongodb
            Sound sound = new Sound();
            sound.setUserId(UserThreadLocal.get().getId());
            sound.setSoundUrl(soundUrl);
            return this.soundApi.saveSound(sound);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    public SoundVo receiveSound() {
        /*
        1. 一个用户一天最多只能接收10条语音
        2. 随机(sid) -> 不重复&不是自己的&该sid在数据库中能查到对应语音记录
        */

        Long userId = UserThreadLocal.get().getId();

        //判断登录用户当天是否还有接收次数,没有直接返回null
        String countKey = "TANHUA_UID_" + userId + "_" + DateUtils.formatDate(new Date(), "yyyyMMdd");
        if (StringUtils.equals(this.redisTemplate.opsForValue().get(countKey), "0")) {
            return null;
        }

        //该登录用户当天还有接受次数,则开始抽取随机语音
        Long soundCountExceptRegister = this.soundApi.querySoundCountExceptRegister(userId);//其他用户发布的sound数
        Long maxSoundSid = this.soundApi.queryMaxSoundSid(); //最大sid
        ArrayList<Sound> sounds = new ArrayList<>();

        if (soundCountExceptRegister <= 10) {
            //判断数据库中符合常规抽取要求的sound个数是否>10,不足则删除重复筛选条件,避免递归内存溢出
            this.selectSoundOptional(sounds, maxSoundSid);
        } else {
            //随机抽取一条符合要求的sound并在redis中存储登录用户和抽取sound的对应关系:避免下次抽取重复语音
            this.selectSoundRandomly(sounds, maxSoundSid);
        }

        Sound sound = sounds.get(0);

        //redis中存储登录用户和当天剩余次数之间的对应关系
        if (this.redisTemplate.hasKey(countKey)) {
            //当天已有该用户的记录则次数-1
            this.redisTemplate.boundValueOps(countKey).increment(-1);
        } else {
            //没有则新增并设置24hrs有效期
            this.redisTemplate.opsForValue().set(countKey, "9", 24, TimeUnit.HOURS);
        }

        //查询该接收sound发布用户的详细信息,赋值给SoundVo对象返回前端
        UserInfo userInfo = this.userInfoService.queryUserInfoByUserId(sound.getUserId());
        if (null == userInfo) {
            return null;
        }
        SoundVo soundVo = new SoundVo();
        soundVo.setId(userInfo.getUserId().intValue());
        soundVo.setAvatar(userInfo.getLogo());
        soundVo.setNickname(userInfo.getNickName());
        soundVo.setGender(userInfo.getSex().name().toLowerCase());
        soundVo.setAge(userInfo.getAge());
        soundVo.setSoundUrl(sound.getSoundUrl());
        soundVo.setRemainingTimes(Integer.parseInt(this.redisTemplate.opsForValue().get(countKey)));
        return soundVo;
    }

    private void selectSoundRandomly(ArrayList<Sound> sounds, Long maxSoundSid) {
        sounds.clear();
        Sound sound = this.soundApi.querySoundBySid(RandomUtils.nextLong(0, maxSoundSid) + 1);
        String Key = "TANHUA_SID_" + UserThreadLocal.get().getId() + "_" + sound.getSid();
        //抽取到的语音不是自己的且不重复
        if (null == sound || sound.getUserId().longValue() == UserThreadLocal.get().getId() || this.redisTemplate.hasKey(Key)) {
            this.selectSoundRandomly(sounds, maxSoundSid);
        } else {
            this.redisTemplate.opsForValue().set(Key, "1", 3, TimeUnit.DAYS);
            sounds.add(sound);
        }
    }

    private void selectSoundOptional(ArrayList<Sound> sounds, Long maxSoundSid) {

        sounds.clear();
        Sound sound = this.soundApi.querySoundBySid(RandomUtils.nextLong(0, maxSoundSid) + 1);
        String Key = "TANHUA_SID_" + UserThreadLocal.get().getId() + "_" + sound.getSid();
        //抽取到的语音不是自己的
        if (null == sound || sound.getUserId().longValue() == UserThreadLocal.get().getId()) {
            this.selectSoundOptional(sounds, maxSoundSid);
        } else {
            this.redisTemplate.opsForValue().set(Key, "1", 15, TimeUnit.DAYS);
            sounds.add(sound);
        }
    }
}
